unit trikes;

{*
Model of trike
TODO: separate wheels as a stand alone model parts and rotate them using BaseAngle, it would be smoother
TODO: smooth start, now it accelerate to full speed immediately
TODO: now cannon fire all the time
}

interface

uses SysUtils, Classes, gl, md3s, vectors, glSoarMain, VUMaths, models;

type
  TTrike = class(TModel)
    Trike, Front, Cannon : TMd3ModelDynamic;

    constructor Create(APath, ASkin : string); virtual;
    procedure Move(AForward,ABack : boolean);
    procedure Stop;
  end;

implementation

constructor TTrike.Create(APath, ASkin : string);
{*
Create 3 body parts
}
begin
  inherited Create;
  // create models
  Trike := TMd3ModelDynamic.Create;
  Front := TMd3ModelDynamic.Create;
  Cannon := TMd3ModelDynamic.Create;
  // load models
//  Trike.ModelStatic := Md3ModelStaticList.Load('data/model/object/flag/', 'flag', 'default'); 
  Trike.ModelStatic := Md3ModelStaticList.Load('data/model/vehicle/trike/', 'trike', 'default'); 
  Front.ModelStatic := Md3ModelStaticList.Load('data/model/vehicle/trike/', 'front', 'default'); 
  Cannon.ModelStatic := Md3ModelStaticList.Load('data/model/vehicle/trike/', 'cannon', 'default');
  // link model 
  Trike.LinkModel('tag_wheel',Front,'tag_wheel');
  Trike.LinkModel('tag_cannon',Cannon,'tag_ground');
  // first base tag
  Trike.Base('tag_ground');
  // default animation
  Trike.SetAnimation('IDLE');
  Front.SetAnimation('IDLE');
  Cannon.SetAnimation('FIRE');
  Speed := 1.0;
  // 
  BaseModel := Trike;
end;

procedure TTrike.Move(AForward,ABack : boolean);
begin
  if AForward then 
  begin
    Rotation.Z := Rotation.Z + Front.BaseAngle / 10;
    Position.X := Position.X - Speed * Sin((Rotation.Z-90)/180*pi);
    Position.Y := Position.Y + Speed * Cos((Rotation.Z-90)/180*pi);
  end;
  if ABack then
  begin
    Rotation.Z := Rotation.Z - Front.BaseAngle / 10;
    Position.X := Position.X + Speed * Sin((Rotation.Z-90)/180*pi);
    Position.Y := Position.Y - Speed * Cos((Rotation.Z-90)/180*pi);
  end;
  // height
  Position.Z := GetTerrainZ(Position.X, Position.Y, Position.Z);
  // rotation according to terrain scope
  GetTerrainScope(Position.X, Position.Y, Position.Z, Rotation.X, Rotation.Y);
  // wheel animation
  if Front.Animation <> 'MOVE' then
    Front.SetAnimation('MOVE');
  if Trike.Animation <> 'MOVE' then
    Trike.SetAnimation('MOVE');
end;

procedure TTrike.Stop;
begin
  if Front.Animation <> 'IDLE' then
    Front.SetAnimation('IDLE');
  if Trike.Animation <> 'IDLE' then
    Trike.SetAnimation('IDLE');
end;

end.